查看原文
其他

NEAR | Robert Yan:基于 Rust 的智能合约开发框架的比较

BeWater BeWater Community 2022-01-01


9 月 4 日的 BeWater DevCon 2021 全球开发者大会上,NEAR 亚洲技术负责人 Robert Yan,从代码层面比较了 Solidity、NEAR、ink!、CosmWasm 和 Solana 的智能合约


通过分析,Rust 的智能合约具有2个特点:


1、从代码实例来看,Rust 智能合约编程语言和 Solidity 语言在语法、语言和数据结构等方面是比较接近的。


2、Rust 智能合约编程语言具备更好的类型安全与内存安全,字节码非常高效的同时体积很小。


BeWater

一、什么是智能合约?


虽然叫智能合约,但是它其实并不 “smart”。我认为叫 Automated Agreement(翻译:自动化协议)可能会更贴近一点,不一定准确。


1990 年初,Nick Szabo 对智能合约作过一个定义:

a set of promises, specified in digital form, including protocols within which the parties perform on these promises.

(翻译:一组以数字形式指定的承诺,包括各方履行这些承诺的协议)



我们现在常见的智能合约一般是区块链上的应用,且去掉了中间人/中介。


比现有的传统系统显得更加便宜、更加快,也更安全,比如在金融领域或其他领域。


还有大家经常提到的一个特点就是可组合性



接着,再对比下智能合约和应用链(AppChain),可以更加清楚地看到智能合约存在的一些问题:

  • 智能合约只能被动地被调用,所以其实并没有自主的智能。

  • 只能在特定的虚拟机或环境中运行,存在限制。

  • 无法配置网络参数,以符合每个应用的特定需求。


相比智能合约,应用链可以配置网络参数,但同时也存在一些缺点

  • 在启动之前需要有一个自己的社区和生态

  • 启动成本比常规的智能合约高很多

  • 目前状态下也不太具备可组合性,跨链交互协议也还处于非常原始的状态


BeWater

二、为什么选择Rust?


Solidity 是否真的 “Solid” ?Solidity 主要的问题有哪些?


台下就有同学就提出:Solidity 原生的 256 位的字长有点过度占用空间,EVM 也存在一些问题,合约调用时有些语义有时候容易造成漏洞。


的确,Solidity 存在着各种问题,但目前阶段其实瑕不掩瑜,毕竟它是以太坊最主流的语言。


说到语言和语言之间的比较,先说一下不同的运行环境之间的比较。现在,另外一种逐渐流行的运行环境是基于 WebAssembly 的。所以,先来比较一下 EVM 和 WASM:



EVM 的优点主要包括:

  • 很强的确定性、可终止的、隔离的环境

  • 是目前最流行的运行环境,各大公链和二层网络都会去支持它


但 EVM 主要的问题包括:

  • 效率低

  • 支持的语言和工具比较有限

  • 较小的生态系统


相比之下,WebAssembly 具有以下优点:

  • 内存安全、沙箱环境和平台独立性

  • 高性能

  • 更小的二进制文件

  • 支持更多语言,包括 Rust、Go、AssemblyScript 等


但 WebAssembly 在区块链领域的应用相对少很多,这是我们可以看到的。


接着,再从语言层面来对比下 Solidity 和 Rust:



Solidity 最主要的的缺陷就是安全性不太好,但优点很多。Solidity 跟 JavaScript 有点类似,虽然 JavaScript 经常被人吐槽,但大家依然还是一直在用它,Solidity 也是类似情况,目前已经占据了第一名的位置。Solidity 语法上和 ECMAScript 比较接近,所以易于学习。也有对类型的支持,有很好的继承支持,对合约开发确实非常友好。


Rust 相对来说也有自己的一些优点,比如它有很强的类型安全、内存安全,也不会有意外的 behaviors。它的社区和生态现在发展也非常快,字节码也非常高效,体积非常小。但 Rust 普遍被诟病的问题就是它的学习曲线非常陡峭,很多人会望而生畏。


BeWater

三、基于 Rust 的智能合约


接下来给大家介绍一下常用的基于 Rust 的智能合约开发框架有哪些,这里我会以 NEAR、ink!、CosmWasm、Solana 为例。其实还有很多,但因为时间关系,就以这几个为例。



这里列了一些我们会去做评估的标准。详细来说,我们可以做非常完整的评估。比如说我们可以从协议角度来讲,它有哪些特性?它为什么这样去设计它的合约开发工具?怎么去初始化合约?怎么调用合约或者跨合约调用?它和账户模型、数据模型、协议模型有哪些关联?怎么做测试?怎么部署?如果要做完整的评估报告,这些都需要加进来。


但是今天演讲时间关系我们不会把所有的都放到上面来讲,我们主要还是看一下代码,让大家有一个直观的感受,后面有兴趣可以进一步看相关的资料进行学习。


Solidity


我们还是以 Solidity 为例,给出一个作为项目模板的例子来做一个比较,这样后面对比的时候会比较清楚。


该例子的 Solidity 合约代码,请点击“阅读原文”中查看。


这个例子叫 ContentTracker,相当于我们有一个网站,上面的一些路径可以放一些广告,其实就等于每个路径都是一个广告位,可以被竞拍。


里面的 ContentRecord 数据结构,保存了广告位的价格、内容和拍卖者。另外,有个 map 保存了每个路径下的 ContentRecord。还有个 contractOwner,我们会有对应的方法去使用它。


这个例子支持了一个竞拍模型,你可以去买广告位,所以它有 purchase() 方法,可传入路径和内容作为参数。方法里会去检查你的出价是多少,出价是否高于该广告位目前已经有的价格,如果是的话,会把它记录下来,之前已经有人买了会把之前的钱退给前一个 Owner ,会把最新的记录,包括价格、内容和 Owner  改成最新的出价人。


另外还有一个 withdraw() 函数可供 contractOwner 调用,为了把赚到的钱拿回来。这个也是为了后面做比较的时候,会用这个函数去看一下那些 Rust 的智能合约开发环境的特点。


还有 getRoute() 函数可以拿到对应的 route 下面的广告词是什么。


这个示例合约一共就 69 行代码,还是比较简单的合约,也没做很多复杂的考虑。



这个例子中,有几个 Highlights,包括使用了 key-value 存储的 mapping,purchase() 函数添加了 payable 修饰器,withdraw() 函数限定了 onlyOwner 修饰器,getRoute() 函数则带有 view 修饰。


NEAR


NEAR 是一个 PoS 的公链,它的主要特点是实现了叫「夜影协议」的分片技术。它的合约开发主要还是基于 Rust 和 AssemblyScript,在 WASM 的运行环境里运行。它采用了水平分片技术,理论上可以做动态的重新分片。基于这种分片的特点可以支持异步的跨合约调用,和 Solidity 的同步调用会有一定的差异。



其他还有很多特点,但因为时间关系,我们直接看代码。


NEAR 的 ContentTracker 合约实现代码,请点击“阅读原文”中查看。


可以看到它头部引用了几个库,包括序列化和反序列化的库,还有 LookupMap 这种数据结构,该结构是和 Solidity 的 mapping 一样存储 key-value 值。


下面定义了 ContentRecord 数据结构,和前面 Solidity 的一样,会有 price、content 和 Owner  变量。


然后下面有个 #[near_bindgen] 注解,这是定义了合约的根结构 ContentTracker,里面存了 values 变量,类型和前面 Solidity 的 mapping 类似,以及 contract_owner 变量。


接着的 Default 实现等价于 Solidity 的 constructor。

purchase() 方法添加了 #[payable] 注解,也等价于 Solidiy 的 payable。


env::attached_deposit() 也和 Solidity 的 msg.value 一样的功能,可读取到转账金额。之后就是对 deposit 做判断,逻辑和前面的其实一样。


转账时,使用了 Promise::new(...).transfer(...),这里其实是一个异步调用。



代码行数总共 75 行,比前面 Solidity 的例子多了几行,但可以看到 Near 的这个智能合约开发还是相当简洁的,只要用原生的 Rust 语言就可以去开发和测试,所以还是支持得比较好。


ink!


ink! 是什么?它是一个在 AppChain 里面,在 Substrate 的环境里面可以运行的 Contract Pallet,是由 Parity 团队实现的。如果是在波卡生态,可以在平行链里跑你的合约。如果是在 Octopus,也可以用租赁安全的方式去启动应用链,也可以在上面执行你的合约。Contract Pallet 也是基于 WebAssembly 用 Rust 语言实现的。


ink! 的特点,不像以太坊和 NEAR 一样的全局共享状态,而是在 AppChain 或平行链里具有一定的可组合性。


另外,如果以后 XCMP 支持比较好的话,有可能也可以实现跨链的智能合约的交互。



案例相关文档,请点击“阅读原文”中查看。

可以看到 ink! 的实现跟 NEAR 比较接近,但是它会有点不一样。比如,第一,它会用 module 的方式来实现。另外,可以看到还使用了不同的宏的实现。刚才我们看到 NEAR 可以用 payable 这种宏,初始化时用到 default,而 ink! 也是类似的,可以加上 #[ink(event)] 注解来定义 event,用 #[ink(topic)] 就和 Solidity 事件中的 indexed 一样可以索引日志。


用 #[ink(storage)] 来定义合约的根结构,和 NEAR 的实现差不多。另外,ink! 还可以定义错误类型,这是在之前的示例中没有用到的,也包括刚才提到的 event。#[ink(constructor)] 则定义了初始化方法,#[ink(message)] 定义则可以读取状态,再增加 payable 就可以进行付费。


withdraw() 的实现稍微复杂一些,因为还做了错误处理,所以没有像 NEAR 的那样简洁。



一共用了 109 行代码,和前面 NEAR 的实现还是挺接近的,我觉得也是挺优雅的实现。


CosmWasm


接下来看看 CosmWasm,这是一个 Cosmos-SDK module,它提供了一种方法,可以在 Cosmos Zone 里面去运行你的智能合约。Cosmos 和基于 Substrate 的应用链,两者的开发环境还是比较接近的。


CosmWasm 从名字也可以看出来,是基于 WASM 的运行环境。另外,虽然 Cosmos 主要是用 Go 语言开发的,但也支持 Rust 的开发环境。


CosmWasm 有一点比较特别,就是把同步调用的跨合约调用给禁止掉了,主要是为了严格防止重入攻击。

另外,CosmWasm 也支持 IBC,所以也可以做一些跨链的操作,但这个可能还需要做更多工作去完善。



代码层面比前面两种会复杂很多,首先它不是单独的文件而是多文件的,包括了 contract.rs、error.rs、lib.rs、msg.rs、state.rs 共 5 个文件。


state.rs 代码,请点击“阅读原文”中查看。


这里面主要定义了一些数据结构,比如 ContentRecord,以及 contractOwner 的

config,还有一些序列化对应的读写的操作。


error.rs 的代码,定义了一个枚举的错误类型,具体请点击“阅读原文”中查看。


可以看到,需要你手动写很多代码,需要自己实现 handler,需要手动写 msg 的处理。这边用到宏的地方比较少,因为它原生没有使用 procedural macro 的定义,所以需要根据原生的 SDK 做很多方法的调用,即需要自己手动写很多代码,但它同样可以实现功能。相对来说会繁琐一些,但基本上也是能实现的。



Solana


最后来讲一下 Solana,它也是可以用 Rust、C 和 C++ 来实现的智能合约。


Solana 有个很好的特性,就是可以支持并发合约的执行,这是其他智能合约不具备的。


另外,Solana 一般使用 Anchor 来开发,如果用原生开发,工作量会比较大。而且,Solona 的智能合约不叫合约,叫 program。



不过,使用 Solana 开发智能合约其实也面临着一些挑战:

account 的存储大小是固定的,需要一开始就指定大小

函数没有返回值,要读取数据需要通过 off chain 的方式去读取,然后自己做一些解析。


原生不支持 key-value 的 map,也为开发带来了些挑战。



相关代码实现,请点击“阅读原文”中查看。


大概就是这样子,基本上能实现基本的功能,但是会有一些限制。比如它没有 ContractOwner 这个概念,前面有的功能也不太好去做,所以也没有实现 withdraw() 的方法。因为函数没有返回值,getRoute 的方法也不太好做,需要自己用 off chain 的方式去实现。


另外刚才也提到几个关键词,用来指定 Solana 特定的需要,来和它智能合约的模型做一些适配。



总结


今天介绍的例子大概就是这样,希望对大家去了解基于 Rust 的智能合约的开发会有一定的帮助。我其实没有做很详细的比较,但是通过这个过程可以看到它和 Solidity 的开发还是比较接近。基本上的模型以及用到的工具,虽然会有一些差异,但是从语法、语言和数据结构这些角度还是非常接近的,特别像 ink! 和 NEAR,其实现还是非常简洁和优雅。


今天 Rust 的介绍就到这里,我们可能还会问的是说未来智能合约语言会往哪个方向去走,其实我没有什么答案。


Solidity 它是什么时候发明的,好像是 2014 年,到今天大概 7 年左右的时间,未来 5 年可能也会有些新的趋势,像 Rust 的智能合约我觉得也值得大家进一步关注,因为 Rust 其实也有挺不错的开发体验,特别像 NEAR、ink! 都建议大家尝试和了解的,我的分享就到这里。



————————————————


历史文章:


1、Avalanche 联合创始人 Ted Yin | 2021 年的区块链基础设施将是什么?2、BeWater 大会纪实|属于开发者的下一个十年,因为相信,所以看见3、BMAN:建设一个不焦虑的开发者社区4、Jolestar | 智能合约编程语⾔,还可能有哪些创新点?5、路印 CTO Steve Guo | 什么样的二层网络才是真正的未来?

6、唯链任之劼 | 权威证明 2.0

7、3Box Joel | 去中心化数字身份与数据,未来在何方?





- 闭门会报名 -


第七期主题:有关跨链、Solana时间:2021.9.15(周三) 晚19:30地点:北京 - 朝阳望京人数:6~8 人面向人群:开发者、行业研究者

: . Video Mini Program Like ,轻点两下取消赞 Wow ,轻点两下取消在看

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存